iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Software Development

從Servlet到Spring MVC系列 第 17

Day16 Servlet - Filter

  • 分享至 

  • xImage
  •  

前言

生活中的過濾器可以過濾水中雜質,再加上活性碳配方前置濾心還可以去除土味;Web中的過濾器可以幫你過濾未授權的使用者,也可以幫你對request與response進行加工。

0、創建module

請參考Day05創建module

一、Filtering

(1)定義

過濾器可以針使用者訪問的目標進行請求行預處理(preprocessing)或後置處理(postprocessing)。

(2)使用場景

  • 進行身分驗證
  • 紀錄訪問响應時間
  • 過濾敏感字符
  • 重新格式化request header or request body
  • audit or logging
  • 壓縮响應流

(3)Filter Flow

https://ithelp.ithome.com.tw/upload/images/20241001/20128084AKgayg36Go.png

二、使用Filter

  • implements filter interface
  • override doFilter method
  • config web.xml
public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("=====LoggingFilter begin=====");
        HttpServletRequest req = (HttpServletRequest) request;
        String requestURI = req.getRequestURI();
        System.out.println("requestURI:"+requestURI);

        chain.doFilter(request, response);

        System.out.println("=====LoggingFilter end=====");
    }
}

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <filter>
    <filter-name>loggingFilter</filter-name>
    <filter-class>com.swj.filters.LoggingFilter</filter-class>
  </filter>
  <!--
      1. /*             過濾全部
      2. /a/            過濾a路徑下的資源
      3. /TargetServlet 對此Servlet進行過濾
  -->
  <filter-mapping>
    <filter-name>loggingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

準備靜態資源

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>

Demo url-pattern為/*
訪問靜態資源
https://ithelp.ithome.com.tw/upload/images/20241001/20128084LDB0IcEFUM.png
訪問Servlet
https://ithelp.ithome.com.tw/upload/images/20241001/20128084xiz4NoKyNK.png

Demo url-pattern為/TargetServlet
訪問靜態資源
https://ithelp.ithome.com.tw/upload/images/20241001/20128084W7ZfboofCf.png
訪問Servlet
https://ithelp.ithome.com.tw/upload/images/20241001/20128084IRsnSReCiz.png

三、Filter life cycle

https://ithelp.ithome.com.tw/upload/images/20241001/20128084eMBuYDzkz9.png

public class LifeCycleFilter implements Filter {

    public LifeCycleFilter() {
        System.out.println("create LifeCycleFilter");
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        System.out.println(filterConfig.getInitParameter("filterParam"));
        System.out.println("init LifeCycleFilter");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("=====LifeCycleFilter begin=====");
        System.out.println("doFilter LifeCycleFilter");
        chain.doFilter(request, response);
        System.out.println("=====LifeCycleFilter begin=====");
    }

    @Override
    public void destroy() {
        System.out.println("destory LifeCycleFilter");
    }
}
<filter>
    <filter-name>LifeCycleFilter</filter-name>
    <filter-class>com.swj.filters.LifeCycleFilter</filter-class>
    <init-param>
      <param-name>filterParam</param-name>
      <param-value>filterValue</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>LifeCycleFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

我們可以看到LifeCycleFilter生命週期的演示,眼尖的你應該有發現我們先執行了LoggingFilter再執行了LifeCycleFilter
https://ithelp.ithome.com.tw/upload/images/20241001/20128084HGGONwfPbT.png

四、Filter Chain執行順序

我們知道多個filter是如何運作的後,是什麼決定他的執行順序呢?
https://ithelp.ithome.com.tw/upload/images/20241001/201280840yFLxRmyWj.png
答案是DD部署描述檔filter-mapping的順序!!!

create Filter1、Filter2、Filter3,Filter2、Filter3程式僅異動編號

public class Filter1 implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("=====Filter1 begin=====");
        chain.doFilter(req, res);
        System.out.println("=====Filter1 end=====");
    }
}
  <filter>
    <filter-name>filter1</filter-name>
    <filter-class>com.swj.filters.Filter1</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter>
    <filter-name>filter2</filter-name>
    <filter-class>com.swj.filters.Filter2</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter>
    <filter-name>filter3</filter-name>
    <filter-class>com.swj.filters.Filter3</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>filter3</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

demo
啟動tomcat訪問TargetServlet
https://ithelp.ithome.com.tw/upload/images/20241001/20128084wmPz9yWB5Z.png
將web.xml filter3順序放到最前面再執行一次
https://ithelp.ithome.com.tw/upload/images/20241001/20128084EV88eGcLlt.png

五、Annotation

透過Annotation的方式加載Filter

  • 透過@WebFilter
  • 透過class name決定執行順序
@WebFilter(
        servletNames = {"filter1"},
        filterName = "filter1",
        urlPatterns = "/*",
        initParams = {@WebInitParam(name="filter1Param",value = "filter1Value")})
public class Filter1 implements Filter {
  //略
}

Reference

  • Head First Servlets and JSP CH13

上一篇
Day15 Servlet - Scope Object
下一篇
Day17 Servlet - Listener
系列文
從Servlet到Spring MVC36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言